// Loesung_von_Aufgabe_10.3_5_Lichtablenkung

// Lichtablenkung durch einen massenreichen Himmelskörper

PVector bezugspunktPosition = new PVector(600, 750); // Virtueller Bezugspunkt, den das Licht erreichen würde, wenn keine Masse im Raum wäre
PVector lichtPosition = new PVector(300, 50); // Die Startposition des echten Lichtstrahls
PVector lichtRichtung = PVector.sub(bezugspunktPosition, lichtPosition).normalize(); // Die Richtung des echten Lichtstrahls zeigt beim Start der Simulation hin zu einem 'virtuellen' Bezugspunkt
PVector massePosition = new PVector(300, 400); // Die Position der Masse, die das Licht des Sterns ablenkt
float masse = 25; // Die Stärke der Raumkrümmung der Masse
float massePhoton = 1; // Die 'Masse' des Photons

void setup()
{
  size(700, 800);

  background(0);

  // Die Masse einzeichnen, die das Licht ablenkt
  noStroke();
  fill(200);
  ellipse(massePosition.x, massePosition.y, 100, 100);

  // Den lichtaussenden Stern einzeichnen
  noStroke();
  fill(255, 255, 0);
  ellipse(lichtPosition.x, lichtPosition.y, 15, 15);
}

void draw()
{
  PVector vektorLichtMasse = PVector.sub(massePosition, lichtPosition); // Die vektorielle Differenz zwischen der Position des Lichtstrahls und der ablenkenden Masse wird gebildet
  float abstandLichtMasse = vektorLichtMasse.mag(); // Der Abstand zwischen dem Lichtstrahl und der Masse wird berechnet
  PVector richtungsvektor = PVector.div(vektorLichtMasse, abstandLichtMasse);

  PVector lichtAblenkung = richtungsvektor.mult(masse * massePhoton).div(abstandLichtMasse * abstandLichtMasse); // Die Ablenkung des Lichtstrahls wird qualitativ berechnet (Formel entspricht nicht der Wirklichkeit) 

  lichtRichtung.add(lichtAblenkung); // Die Richtung, in die sich der Lichtstrahl ausbreitet, wird geändert
  lichtRichtung.normalize(); // Da sich Licht immer mit der selben Geschwindigkeit bewegt, muss die Ausbreitungsrichtung normiert werden.

  lichtPosition.add(lichtRichtung); // Der Lichtstrahl wird entlang der Ausbreitungsrichtung fortbewegt

  // Die Position des Lichtstrahls wird eingezeichnet
  noStroke();
  fill(255, 255, 0);
  ellipse(lichtPosition.x, lichtPosition.y, 2, 2);

  // Wenn der Lichtstrahl die Erde erreicht, stoppt die Simulation und die virtuelle Position des Sterns wird eingezeichnet
  if (lichtPosition.y >= 750)
  {
    // Den 'virtuellen' Lichtstrahl einzeichnen
    float virtuellerSternY = 50;
    float virtuellerSternX = lichtRichtung.x * ((50 - lichtPosition.y) / lichtRichtung.y) + lichtPosition.x;

    noFill();
    stroke(255);
    strokeWeight(2);
    line(lichtPosition.x, 750, virtuellerSternX, virtuellerSternY);

    // Den Stern an der beobachteten Position einzeichnen
    noStroke();
    fill(255);
    ellipse(virtuellerSternX, virtuellerSternY, 15, 15);

    // Erde
    fill(0, 0, 255);
    ellipse(lichtPosition.x, 750, 25, 25);

    noLoop();
  }
}